package com.zxkj.ssm.weixin.shop.mybatis.generator.utils;
import java.io.File;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.*;
import static  com.zxkj.ssm.weixin.shop.basic.Base.notEmpty;
import static com.zxkj.ssm.weixin.shop.utils.FreeMarkerUtils.makeFileByFile;

import com.zxkj.ssm.weixin.shop.basic.Base;
import com.zxkj.ssm.weixin.shop.utils.FreeMarkerUtils;
import lombok.extern.log4j.Log4j;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;

/**
 *@Author 程序媛
 *@Date 2018/6/30 23:43
 *@Description 代码生成类
 *@Version
 */
@Log4j
public class MybatisGeneratorUtil {

	/**
	 *根据模板生成generatorConfig.xml文件
	 * @param jdbcDriver 驱动路径
	 * @param jdbcUrl 链接
	 * @param jdbcUsername 帐号
	 * @param jdbcPassword 密码
	 * @param module  项目模块
	 * @param database 数据库
	 * @param tablePrefix 表前缀
	 * @param packageName 包名前缀
	 * @param lastInsertIdTables 需要insert后返回主键的表集合
	 * @param serviceImplTemplatePath 业务层模板路径
	 * @param serviceTemplatePath 业务实现类的模板路径
     * @param generatorConfigTemplatePath mybatis-generator的comfiguuration模板路径
     * @throws Exception
     */
	public static void generator(
				String jdbcDriver,
				String jdbcUrl,
				String jdbcUsername,
				String jdbcPassword,
				String module,
				String database,
				String tablePrefix,
				String packageName,
				Map<String, String> lastInsertIdTables,
				String serviceImplTemplatePath,
				String serviceTemplatePath,
				String generatorConfigTemplatePath) throws Exception{
				String os = System.getProperty("os.name");
				String basePath = MybatisGeneratorUtil.class.getResource("/").getPath().replace("/target/classes/", "");
				if (os.toLowerCase().startsWith("win")) {
				generatorConfigTemplatePath = MybatisGeneratorUtil.class.getResource(generatorConfigTemplatePath).getPath().replaceFirst("/", "");
				serviceTemplatePath = MybatisGeneratorUtil.class.getResource(serviceTemplatePath).getPath().replaceFirst("/", "");
				serviceImplTemplatePath = MybatisGeneratorUtil.class.getResource(serviceImplTemplatePath).getPath().replaceFirst("/", "");
				basePath = basePath.replaceFirst("/", "");
			} else {
				generatorConfigTemplatePath = MybatisGeneratorUtil.class.getResource(generatorConfigTemplatePath).getPath();
				serviceTemplatePath= MybatisGeneratorUtil.class.getResource(serviceTemplatePath).getPath();
				serviceImplTemplatePath = MybatisGeneratorUtil.class.getResource(serviceImplTemplatePath).getPath();
			}
			String generatorConfigXml = MybatisGeneratorUtil.class.getResource("/").getPath().replace("/target/classes/", "") + "/src/main/resources/generatorConfig.xml";
			String targetProject = basePath;
			String sql = "SELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = '" + database + "' AND table_name LIKE '" + tablePrefix + "_%';";
			log.info("========== 开始生成generatorConfig.xml文件 ==========");
			List<Map<String, Object>> tables = new ArrayList<>();
			try {
				Map<String, Object> table;
			// 查询定制前缀项目的所有表
			JdbcUtil jdbcUtil = new JdbcUtil(jdbcDriver, jdbcUrl, jdbcUsername,jdbcPassword);
			List<Map> result = jdbcUtil.selectByParams(sql, null);
			for (Map map : result) {
				log.info(map.get("TABLE_NAME"));
				table = new HashMap<>(2);
				table.put("table_name", map.get("TABLE_NAME"));
				table.put("model_name", StringUtil.lineToHump(Objects.toString(map.get("TABLE_NAME"))));
				tables.add(table);
			}
			jdbcUtil.release();

			Map<String,Object>root=new HashMap<String,Object>();


			String targetProjectSqlMap = basePath ;
			root.put("tables", tables);
			root.put("mybatisEntity", packageName + ".entity");//实体类
			root.put("mybatisMapperSqlXml", packageName + ".mapper.sql.xml");//MapperXML生成
			root.put("mybatisMapper", packageName + ".mapper.dao");
			root.put("targetProject", targetProject);
			root.put("targetProject_sqlMap", targetProjectSqlMap);
			root.put("tableClass","${tableClass.shortClassName}");
			root.put("mapperSuffix","${mapperSuffix}");

			root.put("jdbcDriver", jdbcDriver);
			/***
			 * 需要注意的是，在xml配置文件中，url中的&符号需要转义成&。比如在tomcat的server.xml中配置数据库连接池时，mysql jdbc url样例如下：
			 * jdbc:mysql://localhost:3306/zheng?useUnicode=true&amp;characterEncoding=utf-8&amp;autoReconnect=true
			 */
			root.put("jdbcUrl", jdbcUrl.replace("&","&amp;"));
			root.put("jdbcUsername", jdbcUsername);
			root.put("jdbcPassword", jdbcPassword);

			root.put("last_insert_id_tables", lastInsertIdTables);
			FreeMarkerUtils.makeFileByFile(generatorConfigTemplatePath.substring(
					generatorConfigTemplatePath.lastIndexOf("/")+1),generatorConfigXml,
					FreeMarkerUtils.getConfiguration("/template/"),root);

			// 删除旧代码
			//deleteDir(new File(targetProject + "/src/main/java/" + packageName.replaceAll("\\.", "/") + "/entity"));
			//deleteDir(new File(targetProject + "/src/main/java/" + packageName.replaceAll("\\.", "/") + "/mapper/dao"));
			//deleteDir(new File(targetProjectSqlMap + "/src/main/java/" + packageName.replaceAll("\\.", "/") + "/mapper/sql/xml"));
			} catch (Exception e) {
				e.printStackTrace();
			}
			log.info("========== 结束生成generatorConfig.xml文件 ==========");

			log.info("========== 开始运行MybatisGenerator ==========");
			List<String> warnings = new ArrayList<>();
			ConfigurationParser cp = new ConfigurationParser(warnings);
			org.mybatis.generator.config.Configuration config = cp.parseConfiguration( new File(generatorConfigXml));
			DefaultShellCallback callback = new DefaultShellCallback(true);
			MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
			myBatisGenerator.generate(null);
			for (String warning : warnings) {
				System.out.println(warning);
			}
			log.info("========== 结束运行MybatisGenerator ==========");

			log.info("========== 开始生成Service ==========");
			String ctime = new SimpleDateFormat("yyyy/M/d").format(new Date());
			StringBuffer servicebuffer = new StringBuffer(basePath);

			  if(Base.notEmpty(module)) {
				  servicebuffer.append(module).append("/").append(module).append("\"-rpc-api\"");
			  }
		    servicebuffer.append("/src/main/java/").append(packageName.replaceAll("\\.", "/")).append("/").append("service");
			String servicePath=servicebuffer.toString();
			StringBuffer	serviceImplBuffer=new StringBuffer(basePath);
			if(Base.notEmpty(module)) {
				serviceImplBuffer.append(module).append("/").append(module).append("\"-rpc-service\"");
			}
			serviceImplBuffer.append("/src/main/java/").append(packageName.replaceAll("\\.", "/")).append("/service/impl");
		    String serviceImplPath=serviceImplBuffer.toString();




			for (int i = 0; i < tables.size(); i++) {
			String model = StringUtil.lineToHump(Objects.toString(tables.get(i).get("table_name")));
			String service = servicePath + "/" + model + "Service.java";
			String serviceImpl = serviceImplPath + "/" + model + "ServiceImpl.java";

			// 生成service
			File serviceFile = new File(service);
			if (!serviceFile.exists()) {
				Map<String, Object> serviceRoot = new HashMap<String, Object>();
				serviceRoot.put("package_name", packageName);
				serviceRoot.put("model", model);
				serviceRoot.put("ctime", ctime);
				FreeMarkerUtils.makeFileByFile(serviceTemplatePath.substring(
						serviceTemplatePath.lastIndexOf("/") + 1), service, FreeMarkerUtils.getConfiguration("/template/"), serviceRoot);
			}

			// 生成serviceImpl
			File serviceImplFile = new File(serviceImpl);
			if (!serviceImplFile.exists()) {
				Map<String,Object> serviceImplRoot = new HashMap<String,Object>();
				serviceImplRoot.put("package_name", packageName);
				serviceImplRoot.put("model", model);
				serviceImplRoot.put("mapper", StringUtil.toLowerCaseFirstOne(model));
				serviceImplRoot.put("ctime", ctime);
				FreeMarkerUtils.makeFileByFile(serviceImplTemplatePath.substring(serviceImplTemplatePath.lastIndexOf("/")+1),serviceImpl, FreeMarkerUtils.getConfiguration("/template/"),serviceImplRoot);
			}
		}
		log.info("========== 结束生成Service ==========");
	}

	// 递归删除非空文件夹
	public static void deleteDir(File dir) {
		if (dir.isDirectory()) {
			File[] files = dir.listFiles();
			for (int i = 0; i < files.length; i++) {
				deleteDir(files[i]);
			}
		}
		dir.delete();
	}


	public static InputStream getResourceAsStream(String path) {
		return Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
	}


/*
	public static void main(String []args){
		try{
		System.out.println(PropertiesLoaderUtils.loadProperties(
				new DefaultResourceLoader().getResource("generator.properties")).getProperty("generator.jdbc.url"));
		}catch(IOException e){
	e.printStackTrace();
		}
	}
*/







}
